package com.gj.xxl.job.admin.core.trigger;

import com.gj.xxl.job.admin.core.config.GjJobScheduleConfig;
import com.gj.xxl.job.admin.core.entity.JobGroup;
import com.gj.xxl.job.admin.core.entity.JobInfo;
import com.gj.xxl.job.admin.core.route.RouteStrategy;
import com.gj.xxl.job.admin.core.route.RouteStrategyEnum;
import com.gj.xxl.job.admin.dao.XxlJobGroupDAO;
import com.gj.xxl.job.core.biz.ExecutorBiz;
import com.gj.xxl.job.core.biz.client.ExecutorBizClient;
import com.gj.xxl.job.core.biz.model.ReturnT;
import com.gj.xxl.job.core.biz.model.TriggerParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ConcurrentHashMap;

/**
 * 触发器，通过 http 远程调用执行器端的
 */
public class GjJobTrigger {
    private static Logger logger = LoggerFactory.getLogger(GjJobTrigger.class);


    private static GjJobTrigger instance = new GjJobTrigger();

    public static GjJobTrigger getInstance() {
        return instance;
    }

    private ExecutorBiz executorBizClient;

    private ConcurrentHashMap<String, ExecutorBizClient> clientMap = new ConcurrentHashMap<>();

    public void trigger(JobInfo jobInfo) {
        XxlJobGroupDAO xxlJobGroupDAO = GjJobScheduleConfig.getInstance().getXxlJobGroupDAO();
        JobGroup xxlJobGroup = xxlJobGroupDAO.findById(jobInfo.getJobGroup());

        //todo 没有实现路由策略，这里直接选择第一个了
        RouteStrategy routeStrategy = RouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), RouteStrategyEnum.ROUND).getRouteStrategy();
        String address = routeStrategy.route(jobInfo.getId(), xxlJobGroup.getRegistryList());
        if (address == null) {
            throw new RuntimeException("没有找到可用的客户端地址");
        }
        executorBizClient = getClient(address);

        //这里没必要重复创建客户端对象，可以缓存下来
//        executorBizClient = new ExecutorBizClient(address, GjJobScheduleConfig.getInstance().getAccessToken());

        ReturnT<String> returnT;
        int retryCount = jobInfo.getExecutorFailRetryCount();
        int i = 0;
        do {
            returnT = executorBizClient.run(new TriggerParam(jobInfo.getId(), jobInfo.getExecutorHandler(), jobInfo.getExecutorBlockStrategy(), jobInfo.getExecutorTimeout()));
            logger.info("第 {} 次远程调用定时任务 job id: {}", i++, jobInfo.getId());
        } while (returnT.getCode() != ReturnT.SUCCESS.getCode() && retryCount-- > 0);
    }

    public ExecutorBiz getClient(String address) {
        ExecutorBizClient client = clientMap.get(address);
        if (client == null) {
            client = new ExecutorBizClient(address, GjJobScheduleConfig.getInstance().getAccessToken());
            clientMap.put(address, client);
        }
        return client;
    }

}

